home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Programming Contest / ~Solutions Submitted / Problem 05 - Team Victory / Solution.cp < prev    next >
Encoding:
Text File  |  1998-06-19  |  6.9 KB  |  268 lines  |  [TEXT/CWIE]

  1. /*
  2. Problem 05 - Database
  3.  
  4. type
  5.     StringsHandle = Handle; // Sequence of Pascal Strings packed together
  6.     DatabaseHandle = Handle; // Must be a real handle
  7.     
  8. procedure DatabaseInit( var database: Handle; field_count: UInt32 );
  9. procedure DatabaseAddEntry( database: Handle; entry: StringsHandle );
  10. procedure DatabaseFindEntry( database: Handle; field: UInt32; const match:
  11. Str255; var entry: StringsHandle );
  12. procedure DatabaseDeleteEntry( database: Handle; field: UInt32; const match:
  13. Str255 );
  14. function DatabaseCount( database: Handle ): UInt32;
  15. procedure DatabaseGetIndEntry( database: Handle; index: UInt32; var entry:
  16. StringsHandle );
  17.  
  18. Your task is to write a set of routines to maintain a database.
  19.  
  20. DatabaseInit creates a new, empty database ready to accept records with
  21. field_count string fields.  The database is stored in the database Handle.
  22.  
  23. DatabaseAddEntry adds an entry (which is a Handle to field_count pascal strings
  24. packed together conceptually numbered 1 to field_count)
  25.  
  26. DatabaseFindEntry finds an entry whose field (between 1 and field_count) string
  27. is exactly equal to match.  The entry is returned in a newly created handle
  28. (which will be disposed of using DisposeHandle).  Return nil if no match is
  29. found.  If more than one entry matches, you must return the earliest added
  30. entry.
  31.  
  32. DatabaseDeleteEntry finds the entry that DatabaseFindEntry would find, and if
  33. found removes it from the database.
  34.  
  35. DatabaseCount returns the number of entries in the database.
  36.  
  37. DatabaseGetIndEntry returns the entries in the Database in the order they were
  38. entered, 1 for the earliest entered, DatabaseCount the last entered.
  39.  
  40. All the database information must be stored in the real Mac memory manager
  41. handle - it will be disposed with DisposeHandle and that must release all
  42. memory, so do not store any extra information outside the handle.  Also, you
  43. must be able to deal with having multiple databases instantiated
  44. simultaneously.
  45.  
  46. You will not be given invalid parameters so you don't need to handle error
  47. checking, and there will be plenty of memory.
  48.  
  49. All strings are case sensitive (ie, treated as eight bit binary data).
  50. */
  51.  
  52. #include <string.h>
  53.  
  54.  
  55. #include "Solution.h"
  56.  
  57. // Fill in your solution and then submit this folder
  58.  
  59. // Team Name: Team Victory!
  60.  
  61. UInt32    gFieldCount;
  62.  
  63.  
  64. OSErr StringFromList( AEDescList *fieldList, StringsHandle *entry );
  65.  
  66.  
  67.  
  68. pascal void DatabaseInit( DatabaseHandle *database, UInt32 field_count )
  69. {
  70.     AEDescList    dbList;
  71.     
  72.     gFieldCount = field_count;
  73.     (void) AECreateList( nil, 0, false, &dbList );
  74.     
  75.     *database = dbList.dataHandle;
  76. }//end DatabaseInit
  77.  
  78. //**************************************************************************************
  79.  
  80. pascal void DatabaseAddEntry( DatabaseHandle database, StringsHandle entry )
  81. {
  82.     OSErr    anErr = noErr;
  83.     
  84.     AEDescList    dbList = { typeAEList, nil };
  85.     dbList.dataHandle = database;
  86.     
  87.     char    handleState = HGetState( (Handle)entry );
  88.     HLock( (Handle)entry );
  89.     char    *entryPtr = *entry;
  90.     
  91.     AEDescList    fieldList;
  92.     
  93.     anErr = AECreateList( nil, 0, false, &fieldList );
  94.     if ( anErr == noErr)
  95.     {
  96.         char    *fieldPtr = entryPtr;
  97.         for ( long index = 1; index <= gFieldCount; index++ )
  98.         {
  99.             char    *strPtr = &fieldPtr[1];    //    get the first character of the field string
  100.             Size    strSize = fieldPtr[0];    //    the size of the string;
  101.             
  102.             (void) AEPutPtr( &fieldList, index, typeChar, strPtr, strSize );
  103.             
  104.             fieldPtr = strPtr + strSize;    //    get the next string
  105.         }
  106.         (void) AEPutDesc( &dbList, 0, &fieldList );
  107.         
  108.         (void) AEDisposeDesc( &fieldList );
  109.     }
  110.     HSetState( (Handle)entry, handleState );
  111.     return;
  112. }//end DatabaseAddEntry
  113.  
  114. //**************************************************************************************
  115.  
  116. pascal void DatabaseFindEntry( DatabaseHandle database, UInt32 keyField, ConstStr255Param matchStr, StringsHandle *entryPtr )
  117. {
  118.     OSErr    anErr = noErr;
  119.     
  120.     AEDescList    dbList = { typeAEList, nil };
  121.     dbList.dataHandle = database;
  122.     
  123.     long    dbCount = 0;
  124.     
  125.     anErr = AECountItems( &dbList, &dbCount );
  126.     
  127.     if ( anErr == noErr )
  128.     {
  129.         for ( long index = 1; index <= dbCount; index++ )
  130.         {
  131.             DescType    keyword;
  132.             AEDescList    fieldList;
  133.             
  134.             anErr = AEGetNthDesc( &dbList, index, typeAEList, &keyword, &fieldList );
  135.             if ( anErr == noErr )
  136.             {
  137.                 DescType    keyword;
  138.                 DescType    actualType;
  139.                 Size        actualSize;
  140.                 char        fieldStr[ 256 ];
  141.                 
  142.                 anErr = AEGetNthPtr( &fieldList, keyField, typeChar, &keyword, &actualType, fieldStr, 255, &actualSize);
  143.                 if ( anErr == noErr )
  144.                 {
  145.                     int        cmpResult = strncmp( (char*)&matchStr[1], fieldStr, matchStr[ 0 ] );
  146.                     if ( cmpResult == 0 )
  147.                     {
  148.                         anErr = StringFromList( &fieldList, entryPtr );
  149.                         break;
  150.                     }
  151.                     else
  152.                     {
  153.                         *entryPtr = nil;
  154.                     }
  155.                 }
  156.                 (void) AEDisposeDesc( &fieldList );
  157.             }
  158.         }
  159.     }
  160.     return;
  161. }
  162.  
  163. pascal void DatabaseDeleteEntry( DatabaseHandle database, UInt32 keyField, ConstStr255Param matchStr )
  164. {
  165.     OSErr    anErr = noErr;
  166.     
  167.     AEDescList    dbList = { typeAEList, nil };
  168.     dbList.dataHandle = database;
  169.     
  170.     long    dbCount;
  171.     
  172.     anErr = AECountItems( &dbList, &dbCount);
  173.     
  174.     if ( anErr == noErr )
  175.     {
  176.         for ( long index = 1; index <= dbCount; index++ )
  177.         {
  178.             DescType    keyword;
  179.             AEDescList    fieldList;
  180.             
  181.             anErr = AEGetNthDesc( &dbList, index, typeAEList, &keyword, &fieldList );
  182.             if ( anErr == noErr )
  183.             {
  184.                 DescType    keyword;
  185.                 DescType    actualType;
  186.                 Size        actualSize;
  187.                 char        fieldStr[ 256 ];
  188.                 
  189.                 anErr = AEGetNthPtr( &fieldList, keyField, typeChar, &keyword, &actualType, fieldStr, 255, &actualSize);
  190.                 (void) AEDisposeDesc( &fieldList );
  191.                 if ( anErr == noErr )
  192.                 {
  193.                     int        cmpResult = strncmp( (char*)&matchStr[1], fieldStr, actualSize );
  194.                     if ( cmpResult == 0 )
  195.                     {
  196.                         anErr = AEDeleteItem( &dbList, index );
  197.                         break;
  198.                     }
  199.                 }
  200.             }
  201.         }
  202.     }
  203.     
  204.     return;
  205. }
  206.  
  207. pascal UInt32 DatabaseCount( DatabaseHandle database )
  208. {
  209.     OSErr    anErr = noErr;
  210.     
  211.     AEDescList    dbList = { typeAEList, nil };
  212.     dbList.dataHandle = database;
  213.     
  214.     UInt32    dbCount;
  215.     
  216.     anErr = AECountItems( &dbList, (long*)&dbCount);
  217.     
  218.     return dbCount;
  219. }
  220.  
  221. pascal void DatabaseGetIndEntry( DatabaseHandle database, UInt32 index, StringsHandle *entry )
  222. {
  223.     OSErr    anErr = noErr;
  224.     
  225.     AEDescList    dbList = { typeAEList, nil };
  226.     dbList.dataHandle = database;
  227.     
  228.     DescType    keyword;
  229.     AEDescList    fieldList;
  230.     
  231.     anErr = AEGetNthDesc( &dbList, index, typeAEList, &keyword, &fieldList );
  232.     if ( anErr == noErr )
  233.     {
  234.         anErr = StringFromList( &fieldList, entry );
  235.     }
  236.     (void) AEDisposeDesc( &fieldList );
  237.     
  238.     return;
  239. }//end DatabaseGetIndEntry
  240.  
  241.  
  242. OSErr StringFromList( AEDescList *fieldList, StringsHandle *entry )
  243. {
  244.     long    fieldCount;
  245.     OSErr    anErr = noErr;
  246.     
  247.     *entry = NewHandle( 0 );
  248.     
  249.     anErr = AECountItems( fieldList, &fieldCount);
  250.     if ( anErr == noErr )
  251.     {
  252.         for ( long index = 1; index <= fieldCount; index++ )
  253.         {
  254.             DescType    keyword;
  255.             DescType    actualType;
  256.             Size        actualSize;
  257.             char        fieldStr[ 256 ];
  258.             
  259.             anErr = AEGetNthPtr( fieldList, index, typeChar, &keyword, &actualType, &fieldStr[1], 255, &actualSize );
  260.             if ( anErr == noErr )
  261.             {
  262.                 fieldStr[0] = actualSize;
  263.                 PtrAndHand( fieldStr, *entry, actualSize + 1 );
  264.             }
  265.         }
  266.     }
  267.     return anErr;
  268. }//end StringFromList